﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Acms.Bll.Tests
{
    [TestClass]
    public class PostsTests : Base
    {
        [TestMethod]
        public void GetById_With_IncorrectId_IncorrectDate_ReturnsNull()
        {
            Assert.IsNull(Acms.Bll.Post.GetById(_TestSites.First().Id, int.MaxValue, null));
        }

        [TestMethod]
        public void GetById_With_CorrectId_IncorrectDate_ReturnsNull()
        {
            Assert.IsNull(Acms.Bll.Post.GetById(_TestSites.First().Id, _TestPosts[0].Id, null));
        }

        [TestMethod]
        public void GetById_With_CorrectId_CorrectDate_ReturnsNotNull()
        {
            Assert.IsNotNull(Acms.Bll.Post.GetById(_TestSites.First().Id, _TestPosts[0].Id, _TestPosts[0].PublishFrom.ToLocalTime()));
        }

        [TestMethod]
        public void GetById_With_CorrectId_CorrectPending_ReturnsNotNull()
        {
            Assert.IsNotNull(Acms.Bll.Post.GetById(_TestSites.First().Id, _TestPosts[3].Id, null));
        }

        [TestMethod]
        public void GetByGuid_With_CorrectId_CorrectPending_ReturnsNotNull()
        {
            Assert.IsNotNull(Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, null));
        }

        [TestMethod]
        public void GetByGuid_With_CorrectId_CorrectPending_PopulatesCorrectly()
        {
            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, null);
            ValidateProperties(tmp, _TestPosts[3]);
            tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, _TestPosts[1].PublishTo.Value.ToLocalTime().AddDays(1));
            ValidateProperties(tmp, _TestPosts[2]);
            tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, _TestPosts[0].PublishTo.Value.ToLocalTime());
            ValidateProperties(tmp, _TestPosts[1]);
            tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, _TestPosts[0].PublishTo.Value.ToLocalTime().AddHours(-1));
            ValidateProperties(tmp, _TestPosts[0]);
        }

        [TestMethod]
        public void GetAllByPostGuid_With_IncorrectGuid_ReturnsEmptyList()
        {
            var tmp = Post.GetAllByPostGuid(Guid.NewGuid());
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count);
        }

        [TestMethod]
        public void GetAllByPostGuid_With_CorrectGuid_ReturnsPopulatedList()
        {
            var tmp = Post.GetAllByPostGuid(_TestPosts[0].PostGuid);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(4, tmp.Count);
        }

        [TestMethod]
        public void GetAllByPostGuid_With_CorrectGuid_PopulatesCorrectly()
        {
            var tmp = Post.GetAllByPostGuid(_TestPosts[0].PostGuid);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(4, tmp.Count);
            ValidateProperties(tmp[0], _TestPosts[3]);
            ValidateProperties(tmp[1], _TestPosts[2]);
            ValidateProperties(tmp[2], _TestPosts[1]);
            ValidateProperties(tmp[3], _TestPosts[0]);
        }

        [TestMethod]
        public void GetAllByParentGuid_With_CorrectGuid_NullVersion_PopulatesCorrectly()
        {
            var tmp = Post.GetAllByParentGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, null);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count);
            Assert.AreEqual("Child 1", tmp[0].DisplayName);
            Assert.AreEqual("Child 2", tmp[1].DisplayName);
            ValidateProperties(tmp[0], _TestPosts[5]);
            ValidateProperties(tmp[1], _TestPosts[7]);
        }

        [TestMethod]
        public void GetAllByParentGuid_With_CorrectGuid_NotNullVersion_PopulatesCorrectly()
        {
            var tmp = Post.GetAllByParentGuid(_TestSites.First().Id, _TestPosts[0].PostGuid, _TestPosts[0].PublishFrom.ToLocalTime().Value.AddDays(5));
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count);
            Assert.AreEqual("Child 1", tmp[0].DisplayName);
            Assert.AreEqual("Child 2", tmp[1].DisplayName);
            ValidateProperties(tmp[0], _TestPosts[4]);
            ValidateProperties(tmp[1], _TestPosts[6]);
        }

        [TestMethod]
        public void GetAllBySiteIdAndParentPath_ReturnsEmptyForIncorectSiteId()
        {
            var tmp = Post.GetAllBySiteIdAndParentPath(int.MaxValue, "~/", null);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count);
        }

        [TestMethod]
        public void GetAllBySiteIdAndParentPath_ReturnsEmptyForIncorectPath()
        {
            var tmp = Post.GetAllBySiteIdAndParentPath(_TestSites[0].Id, "~/RUBBISH", null);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count);
        }

        [TestMethod]
        public void GetAllBySiteIdAndParentPath_ReturnsEmptyForIncorectDate()
        {
            var datetime = _Context.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate.Value).Min().ToLocalTime().AddDays(-1);
            var tmp = Post.GetAllBySiteIdAndParentPath(_TestSites[0].Id, "~/", datetime);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count);
        }

        [TestMethod]
        public void GetAllBySiteIdAndParentPath_PopulatesCorretlyForPending()
        {
            var tmp = Post.GetAllBySiteIdAndParentPath(_TestSites[0].Id, "~/", null);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count);
            ValidateProperties(tmp[0], _TestPosts[5]);
            ValidateProperties(tmp[1], _TestPosts[7]);
        }

        [TestMethod]
        public void GetAllBySiteIdAndParentPath_PopulatesCorretlyForLive()
        {
            var datetime = _TestPosts[0].PublishFrom.ToLocalTime();
            var tmp = Post.GetAllBySiteIdAndParentPath(_TestSites[0].Id, "~/", datetime);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(2, tmp.Count);
            ValidateProperties(tmp[0], _TestPosts[4]);
            ValidateProperties(tmp[1], _TestPosts[6]);
            Assert.AreEqual(datetime, tmp[0].SiteVersion);
            Assert.AreEqual(datetime, tmp[1].SiteVersion);
        }

        [TestMethod]
        public void GetAllWhereRequiresPublishing_WithIncorrectSiteIdReturnEmpty()
        {
            var tmp = Post.GetAllWhereRequiresPublishing(int.MaxValue);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count);
        }

        [TestMethod]
        public void GetAllWhereRequiresPublishing_WithCorrectSiteIdPopulatesCorrectly()
        {
            var tmp = Post.GetAllWhereRequiresPublishing(_TestSites[0].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(6, tmp.Count);
            ValidateProperties(tmp[0], _TestPosts[3]);
            ValidateProperties(tmp[1], _TestPosts[5]);
            ValidateProperties(tmp[2], _TestPosts[7]);
            ValidateProperties(tmp[3], _TestPosts[8]);
            ValidateProperties(tmp[4], _TestPosts[9]);
            ValidateProperties(tmp[5], _TestPosts[10]);
            tmp.ForEach(x => Assert.IsNull(x.SiteVersion, string.Format("Post with Id {0} expected null SiteVersion Property by found {1}", x.Id, x.SiteVersion)));
            tmp.ForEach(x => Assert.IsTrue(x.RequiresPublishing, string.Format("Post with Id {0} expected True for RequresPublishing Property by found false", x.Id)));
        }

        [TestMethod]
        public void GetBySiteIdAndPath_ReturnsNull_WithIncorectSiteId()
        {
            var tmp = Post.GetBySiteIdAndPath(int.MaxValue, "~/Child_1", null);
            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void GetBySiteIdAndPath_ReturnsNull_WithIncorectPath()
        {
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Rubbish", null);
            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void GetBySiteIdAndPath_ReturnsNull_WithIncorectDate()
        {
            var datetime = _Context.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate.Value).Min().ToLocalTime().AddDays(-1);
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Child_1", datetime);
            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void GetBySiteIdAndPath_WithDate_PopulatesCorretly()
        {
            var datetime = _Context.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate.Value).Min().ToLocalTime();
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Child_1", datetime);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestPosts[4]);
        }

        [TestMethod]
        public void GetBySiteIdAndPath_WithTrailingSlash_PopulatesCorretly()
        {
            var datetime = _Context.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate.Value).Min().ToLocalTime();
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Child_1/", datetime);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestPosts[4]);
        }

        [TestMethod]
        public void GetBySiteUrlAndPath_PopulatesCorretly()
        {
            var datetime = _Context.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate.Value).Min().ToLocalTime();
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Child_1/", datetime);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestPosts[4]);
        }

        [TestMethod]
        public void GetBySiteIdAndPath_WithPending_PopulatesCorretly()
        {
            var tmp = Post.GetBySiteIdAndPath(_TestSites[0].Id, "~/Child_1", null);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestPosts[5]);
        }

        [TestMethod]
        public void UpdateTest()
        {
            var tmp = Post.GetById(_TestSites.First().Id, _TestPosts[7].Id, _TestPosts[7].PublishFrom.ToLocalTime());
            Assert.IsNotNull(tmp);

            var tmpCID = (byte[])tmp.ConcurencyId;
            tmp.DeveloperLocked = !tmp.DeveloperLocked;
            tmp.DisplayName = "Updated Display Name";
            tmp.Name = "UpdatedName";
            tmp.Notes = "Updated Notes";
            tmp.ReadyToPublish = !_TestPosts[7].ReadyToPublish;
            tmp.RequiresPublishing = !_TestPosts[7].RequiresPublishing;
            tmp.Sequence = 5;
            tmp.Summary = "Updated Summary";

            tmp.Update();

            var newCID = (byte[])tmp.ConcurencyId;
            var cidupdated = false;
            for (int i = 0; i < newCID.Length; i++ )
            {
                if (newCID[i] != tmpCID[i])
                {
                    cidupdated = true;
                }
            }
            Assert.IsTrue(cidupdated);

            Assert.AreEqual(!_TestPosts[7].DeveloperLocked, tmp.DeveloperLocked);
            Assert.AreEqual("Updated Display Name", tmp.DisplayName);
            Assert.AreEqual("UpdatedName", tmp.Name); 
            Assert.AreEqual("Updated Notes", tmp.Notes);
            Assert.AreEqual(!_TestPosts[7].ReadyToPublish, tmp.ReadyToPublish);
            Assert.AreEqual(!_TestPosts[7].RequiresPublishing, tmp.RequiresPublishing);
            Assert.AreEqual(5, tmp.Sequence);
            Assert.AreEqual("Updated Summary", tmp.Summary);

            tmp = Post.GetById(_TestSites.First().Id, _TestPosts[7].Id, _TestPosts[7].PublishFrom.ToLocalTime());

            Assert.AreEqual(!_TestPosts[7].DeveloperLocked, tmp.DeveloperLocked);
            Assert.AreEqual("Updated Display Name", tmp.DisplayName);
            Assert.AreEqual("UpdatedName", tmp.Name);
            Assert.AreEqual("Updated Notes", tmp.Notes);
            Assert.AreEqual(!_TestPosts[7].ReadyToPublish, tmp.ReadyToPublish);
            Assert.AreEqual(!_TestPosts[7].RequiresPublishing, tmp.RequiresPublishing);
            Assert.AreEqual(5, tmp.Sequence);
            Assert.AreEqual("Updated Summary", tmp.Summary);

            ValidateProperties(tmp, new DBDataContext().Posts.Where(x => x.Id == tmp.Id).Single());

        }

        [TestMethod]
        public void InsertTest()
        {
            var parent = _TestPosts.Where(x => x.PostPositions.Where(y => y.PublishDate == null).Count() == 1).First();
            var tmp = Acms.Bll.Post.CreateInstance();
            tmp.TemplateId = _TestTemplates.First().Id;
            tmp.ParentGuid = parent.PostGuid;
            tmp.SiteId = parent.SiteId;
            tmp.DisplayName = "Insert Test";
            tmp.DeveloperLocked = true;
            tmp.Name = "InsertTest";
            tmp.Notes = "Insert Notes";
            tmp.Summary = "Insert Summary";

            tmp.Update();

            Assert.IsTrue(tmp.Id > 0);
            Assert.IsNotNull(tmp.ConcurencyId);
            Assert.IsTrue(tmp.CreatedDateTime > DateTime.MinValue);
            Assert.AreEqual(true, tmp.DeveloperLocked);
            Assert.AreEqual("Insert Test", tmp.DisplayName);
            Assert.AreEqual("InsertTest", tmp.Name);
            Assert.AreEqual((Acms.Bll.Template.NodeTypes)_TestTemplates.First().NodeType, tmp.NodeType);
            Assert.AreEqual("Insert Notes", tmp.Notes);
            Assert.IsNotNull(tmp.Parent);
            Assert.AreEqual(parent.Id, tmp.Parent.Id);
            Assert.AreEqual(parent.PostGuid, tmp.ParentGuid);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/"), tmp.ParentPath);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/default.aspx?AcmsSV=Pending"), tmp.ParentUrl);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest"), tmp.Path);
            Assert.AreNotEqual(Guid.Empty, tmp.PostGuid);
            Assert.AreEqual(null, tmp.PublishFrom);
            Assert.AreEqual(null, tmp.PublishTo);
            Assert.AreEqual(false, tmp.ReadyToPublish);
            //ToDo: Suspect this should actually be true
            Assert.AreEqual(false, tmp.RequiresPublishing);
            Assert.AreEqual(2, tmp.Sequence);
            Assert.AreEqual(parent.SiteId, tmp.SiteId);
            Assert.AreEqual(parent.Site.Name, tmp.SiteName);
            Assert.AreEqual(null, tmp.SiteVersion);
            Assert.AreEqual("Insert Summary", tmp.Summary);
            Assert.IsNotNull(tmp.Template);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.TemplateName);
            Assert.AreEqual(null, tmp.ThumbnailId);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest.aspx?AcmsSV=Pending"), tmp.Url);

            var tmpId = tmp.Id;
            byte[] tmpCID = (byte[])tmp.ConcurencyId;
            DateTime tmpCreated = tmp.CreatedDateTime;
            Guid tmpGuid = tmp.PostGuid;
            tmp = Acms.Bll.Post.GetById(_TestSites.First().Id, tmpId, null);

            Assert.IsNotNull(tmp);

            Assert.AreEqual(tmpId, tmp.Id);
            AssertHelper.AreEqual(tmpCID, (byte[])tmp.ConcurencyId);
            AssertHelper.AreEqual(tmpCreated, tmp.CreatedDateTime, 1000);
            Assert.AreEqual(true, tmp.DeveloperLocked);
            Assert.AreEqual("Insert Test", tmp.DisplayName);
            Assert.AreEqual("InsertTest", tmp.Name);
            Assert.AreEqual((Acms.Bll.Template.NodeTypes)_TestTemplates.First().NodeType, tmp.NodeType);
            Assert.AreEqual("Insert Notes", tmp.Notes);
            Assert.IsNotNull(tmp.Parent);
            Assert.AreEqual(parent.Id, tmp.Parent.Id);
            Assert.AreEqual(parent.PostGuid, tmp.ParentGuid);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/"), tmp.ParentPath);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/default.aspx?AcmsSV=Pending"), tmp.ParentUrl);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest"), tmp.Path);
            Assert.AreNotEqual(Guid.Empty, tmp.PostGuid);
            Assert.AreEqual(null, tmp.PublishFrom);
            Assert.AreEqual(null, tmp.PublishTo);
            Assert.AreEqual(false, tmp.ReadyToPublish);
            Assert.AreEqual(false, tmp.RequiresPublishing);
            Assert.AreEqual(_TestPosts.Where(x => x.ParentGuid == _TestPosts.First().PostGuid && x.PostPositions.Where(y => y.PublishDate == null).Count() == 1).Count(), tmp.Sequence);
            Assert.AreEqual(_TestSites[0].Id, tmp.SiteId);
            Assert.AreEqual(_TestSites[0].Name, tmp.SiteName);
            Assert.AreEqual(null, tmp.SiteVersion);
            Assert.AreEqual("Insert Summary", tmp.Summary);
            Assert.IsNotNull(tmp.Template);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.TemplateName);
            Assert.AreEqual(null, tmp.ThumbnailId);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest.aspx?AcmsSV=Pending"), tmp.Url);

            ValidateProperties(tmp, new DBDataContext().Posts.Where(x => x.Id == tmpId).Single());
        }

        [TestMethod]
        public void InsertTest_WithExistingPublishFromSet()
        {
            var parent = _TestPosts.Where(x => x.PostPositions.Where(y => y.PublishDate != null).Count() == 1).OrderByDescending(x => x.PostPositions.First().PublishDate).First();
            var tmp = Acms.Bll.Post.CreateInstance();
            tmp.TemplateId = _TestTemplates.First().Id;
            tmp.ParentGuid = parent.PostGuid;
            tmp.SiteId = parent.SiteId;
            tmp.DisplayName = "Insert Test";
            tmp.DeveloperLocked = true;
            tmp.Name = "InsertTest";
            tmp.Notes = "Insert Notes";
            tmp.Summary = "Insert Summary";
            tmp.PublishFrom = parent.PublishFrom.ToLocalTime();
            //validate that the publish from is actually set
            Assert.IsNotNull(parent.PublishFrom);

            tmp.Update();

            Assert.IsTrue(tmp.Id > 0);
            Assert.IsNotNull(tmp.ConcurencyId);
            Assert.IsTrue(tmp.CreatedDateTime > DateTime.MinValue);
            Assert.AreEqual(true, tmp.DeveloperLocked);
            Assert.AreEqual("Insert Test", tmp.DisplayName);
            Assert.AreEqual("InsertTest", tmp.Name);
            Assert.AreEqual((Acms.Bll.Template.NodeTypes)_TestTemplates.First().NodeType, tmp.NodeType);
            Assert.AreEqual("Insert Notes", tmp.Notes);
            Assert.IsNotNull(tmp.Parent);
            Assert.AreEqual(parent.Id, tmp.Parent.Id);
            Assert.AreEqual(parent.PostGuid, tmp.ParentGuid);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/"), tmp.ParentPath);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/default.aspx?AcmsSV=2025%2f01%2f01+14%3a00"), tmp.ParentUrl);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest"), tmp.Path);
            Assert.AreNotEqual(Guid.Empty, tmp.PostGuid);
            Assert.AreEqual(parent.PublishFrom.ToLocalTime(), tmp.PublishFrom);
            Assert.AreEqual(null, tmp.PublishTo);
            Assert.AreEqual(false, tmp.ReadyToPublish);
            Assert.AreEqual(false, tmp.RequiresPublishing);
            Assert.AreEqual(2, tmp.Sequence);
            Assert.AreEqual(parent.SiteId, tmp.SiteId);
            Assert.AreEqual(parent.Site.Name, tmp.SiteName);
            Assert.AreEqual(parent.PublishFrom.ToLocalTime(), tmp.SiteVersion);
            Assert.AreEqual("Insert Summary", tmp.Summary);
            Assert.IsNotNull(tmp.Template);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.TemplateName);
            Assert.AreEqual(null, tmp.ThumbnailId);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest.aspx?AcmsSV=2025%2f01%2f01+14%3a00"), tmp.Url);

            var tmpId = tmp.Id;
            byte[] tmpCID = (byte[])tmp.ConcurencyId;
            DateTime tmpCreated = tmp.CreatedDateTime;
            Guid tmpGuid = tmp.PostGuid;
            tmp = Acms.Bll.Post.GetById(_TestSites.First().Id, tmpId, parent.PublishFrom.ToLocalTime());

            Assert.IsNotNull(tmp);

            Assert.AreEqual(tmpId, tmp.Id);
            AssertHelper.AreEqual(tmpCID, (byte[])tmp.ConcurencyId);
            AssertHelper.AreEqual(tmpCreated, tmp.CreatedDateTime);
            Assert.AreEqual(true, tmp.DeveloperLocked);
            Assert.AreEqual("Insert Test", tmp.DisplayName);
            Assert.AreEqual("InsertTest", tmp.Name);
            Assert.AreEqual((Acms.Bll.Template.NodeTypes)_TestTemplates.First().NodeType, tmp.NodeType);
            Assert.AreEqual("Insert Notes", tmp.Notes);
            Assert.IsNotNull(tmp.Parent);
            Assert.AreEqual(parent.Id, tmp.Parent.Id);
            Assert.AreEqual(parent.PostGuid, tmp.ParentGuid);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/"), tmp.ParentPath);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/default.aspx?AcmsSV=2025%2f01%2f01+14%3a00"), tmp.ParentUrl);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest"), tmp.Path);
            Assert.AreNotEqual(Guid.Empty, tmp.PostGuid);
            Assert.AreEqual(parent.PublishFrom.ToLocalTime(), tmp.PublishFrom);
            Assert.AreEqual(null, tmp.PublishTo);
            Assert.AreEqual(false, tmp.ReadyToPublish);
            Assert.AreEqual(false, tmp.RequiresPublishing);
            Assert.AreEqual(_TestPosts.Where(x => x.ParentGuid == _TestPosts.First().PostGuid && x.PostPositions.Where(y => y.PublishDate == null).Count() == 1).Count(), tmp.Sequence);
            Assert.AreEqual(_TestSites[0].Id, tmp.SiteId);
            Assert.AreEqual(_TestSites[0].Name, tmp.SiteName);
            Assert.AreEqual(parent.PublishFrom.ToLocalTime(), tmp.SiteVersion);
            Assert.AreEqual("Insert Summary", tmp.Summary);
            Assert.IsNotNull(tmp.Template);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.TemplateName);
            Assert.AreEqual(null, tmp.ThumbnailId);
            Assert.AreEqual(string.Concat(parent.PostPositions.First().ParentPath, parent.Name, "/InsertTest.aspx?AcmsSV=2025%2f01%2f01+14%3a00"), tmp.Url);

            ValidateProperties(tmp, new DBDataContext().Posts.Where(x => x.Id == tmpId).Single());

            //Check pending version has been created
            var pending = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, tmp.PostGuid, null);

            Assert.IsNotNull(pending);

            Assert.AreNotEqual(tmp.Id, pending.Id);
            AssertHelper.AreEqual(tmp.CreatedDateTime, pending.CreatedDateTime, 1000);
            Assert.AreEqual(tmp.DeveloperLocked, pending.DeveloperLocked);
            Assert.AreEqual(tmp.DisplayName, pending.DisplayName);
            Assert.AreEqual(tmp.Name, pending.Name);
            Assert.AreEqual(tmp.NodeType, pending.NodeType);
            Assert.AreEqual(tmp.Notes, pending.Notes);
            Assert.AreEqual(tmp.ParentGuid, pending.ParentGuid);
            Assert.AreEqual(tmp.Path, pending.Path);
            Assert.AreEqual(tmp.PostGuid, pending.PostGuid);
            Assert.AreEqual(null, pending.PublishFrom);
            Assert.AreEqual(null, pending.PublishTo);
            Assert.AreEqual(false, pending.ReadyToPublish);
            Assert.AreEqual(false, pending.RequiresPublishing);
            Assert.AreEqual(tmp.Sequence, pending.Sequence);
            Assert.AreEqual(tmp.SiteId, pending.SiteId);
            Assert.AreEqual(tmp.SiteName, pending.SiteName);
            Assert.AreEqual(null, pending.SiteVersion);
            Assert.AreEqual(tmp.Summary, pending.Summary);
            Assert.AreEqual(tmp.TemplateId, pending.TemplateId);
            Assert.AreEqual(tmp.TemplateName, pending.TemplateName);
            Assert.AreEqual(tmp.ThumbnailId, pending.ThumbnailId);
        }

        [TestMethod]
        public void PublishTest_WithNoChildren_ToExistsingPublishDate()
        {
            //Get all the distinct times
            var distinctDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x);
            //take and existing date in the future from published posts
            var dateTime = distinctDateTimes.First();
            //Get the post we are publishing  Child 1_1 postion 8
            var postGuid = _TestPosts[8].PostGuid;
            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, postGuid, null);
            Assert.IsNotNull(tmp);

            tmp.Publish(false, false, dateTime, null);

            Assert.AreEqual(dateTime, tmp.PublishFrom);

            var collection = Acms.Bll.Post.GetAllByPostGuid(tmp.PostGuid);
            Assert.AreEqual(2, collection.Count);
            Assert.AreEqual(null, collection.First().PublishFrom);
            Assert.AreEqual(dateTime, collection.Skip(1).First().PublishFrom);
            //Check that there are still the same no of distinct dates
            Assert.AreEqual(distinctDateTimes.Count(), _FreshContext.PostPositions.Where(x => x.PublishDate.HasValue).Select(x => x.PublishDate).Distinct().Count());
        }


        [TestMethod]
        public void PublishTest_WithNoChildren_ToNewPublishDate()
        {
            //Get all the distinct times
            var distinctDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x).ToList();
            //take and existing date in the future from published posts and add a day to it
            var dateTime = distinctDateTimes.First().AddDays(10);
            //Get the post we are publishing  Child 1_1 postion 8
            var postGuid = _TestPosts[8].PostGuid;
            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, postGuid, null);
            Assert.IsNotNull(tmp);

            tmp.Publish(false, false, dateTime, null);

            Assert.AreEqual(dateTime, tmp.PublishFrom);

            var collection = Acms.Bll.Post.GetAllByPostGuid(tmp.PostGuid);
            Assert.AreEqual(2, collection.Count);
            Assert.AreEqual(null, collection.First().PublishFrom);
            Assert.AreEqual(dateTime, collection.Skip(1).First().PublishFrom);
            //Check that there is only one extra date
            var currentDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x);
            Assert.AreEqual(currentDateTimes.First(), dateTime);
            Assert.AreEqual(distinctDateTimes.Count() + 1, currentDateTimes.Count());
            //check each posts has a new post position with the new date
            foreach (var post in _FreshContext.Posts.Where(x => x.PublishFrom.HasValue && x.PublishFrom.Value <= dateTime && x.PublishTo == null))
            {
                Assert.AreEqual(1, post.PostPositions.Where(x => x.PublishDate.HasValue && x.PublishDate.Value == dateTime).Count(), string.Format("Post {0} dosnt have a post position record for {1:dd/MM/yyyy HH:mm}", post.DisplayName, dateTime));
            }
        }

        [TestMethod]
        public void PublishTest_WithNoChildren_ToNewPublishDateWithOverlappingOtherDates()
        {
            //Get all the distinct times
            var distinctDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x).ToList();
            //take and existing date in the future from published posts and add a day to it
            var dateTime = distinctDateTimes.First().AddDays(-1);
            //Get the post we are publishing  Child 1_1 postion 8
            var postGuid = _TestPosts[8].PostGuid;
            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, postGuid, null);
            Assert.IsNotNull(tmp);

            tmp.Publish(false, false, dateTime, null);

            Assert.AreEqual(dateTime, tmp.PublishFrom);

            var collection = Acms.Bll.Post.GetAllByPostGuid(tmp.PostGuid);
            Assert.AreEqual(2, collection.Count);
            Assert.AreEqual(null, collection.First().PublishFrom);
            Assert.AreEqual(dateTime, collection.Skip(1).First().PublishFrom);
            //Check that there is only one extra date
            var currentDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x);
            Assert.AreEqual(currentDateTimes.Skip(1).First(), dateTime);
            Assert.AreEqual(distinctDateTimes.Count() + 1, currentDateTimes.Count());
            //check each posts has a new post position with the new date
            foreach (var post in _FreshContext.Posts.Where(x => x.PublishFrom.HasValue && x.PublishFrom.Value <= dateTime && x.PublishTo == null))
            {
                Assert.AreEqual(1, post.PostPositions.Where(x => x.PublishDate.HasValue && x.PublishDate.Value == dateTime).Count(), string.Format("Post {0} dosnt have a post position record for {1:dd/MM/yyyy HH:mm}", post.DisplayName, dateTime));
            }
            //check that the Child 1_1 has position records for each date
            var expectedDates = distinctDateTimes.Where(x => x >= dateTime).OrderBy(x => x).ToList();
            expectedDates.Insert(0, dateTime);
            var actualPositionRecords = _FreshContext.PostPositions.Where(x => x.PostId == tmp.Id).OrderBy(x => x.PublishDate).ToList();
            Assert.AreEqual(expectedDates.Count(), actualPositionRecords.Count());
            for (int i = 0; i < expectedDates.Count(); i++)
            {
                Assert.IsNotNull(actualPositionRecords[i].PublishDate);
                Assert.AreEqual(expectedDates[i], actualPositionRecords[i].PublishDate.Value);
            }
        }

        [TestMethod]
        public void PublishTest_WithChildren_ToNewPublishDate()
        {
            //Get all the distinct times
            var distinctDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x).ToList();
            //take and existing date in the future from published posts and add a day to it
            var dateTime = distinctDateTimes.First().AddDays(10);
            //Get the post we are publishing HomePage postion 0
            var postGuid = _TestPosts[0].PostGuid;
            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, postGuid, null);
            Assert.IsNotNull(tmp);

            tmp.Publish(false, false, dateTime, null);

            Assert.AreEqual(dateTime, tmp.PublishFrom);

            var collection = Acms.Bll.Post.GetAllByPostGuid(tmp.PostGuid);
            Assert.AreEqual(5, collection.Count);
            Assert.AreEqual(null, collection.First().PublishFrom);
            Assert.AreEqual(dateTime, collection.Skip(1).First().PublishFrom);
            //Check that there is only one extra date
            var currentDateTimes = _Context.PostPositions.Where(x => x.PublishDate != null).Select(x => x.PublishDate.Value).Distinct().OrderByDescending(x => x);
            Assert.AreEqual(currentDateTimes.First(), dateTime);
            Assert.AreEqual(distinctDateTimes.Count() + 1, currentDateTimes.Count());
            //check each posts has a new post position with the new date
            foreach (var post in _FreshContext.Posts.Where(x => x.PublishFrom.HasValue && x.PublishFrom.Value <= dateTime && x.PublishTo == null))
            {
                Assert.AreEqual(1, post.PostPositions.Where(x => x.PublishDate.HasValue && x.PublishDate.Value == dateTime).Count(), string.Format("Post {0} dosnt have a post position record for {1:dd/MM/yyyy HH:mm}", post.DisplayName, dateTime));
            }
        }

        [TestMethod]
        public void RenameTest_WithChildren()
        {
            var siteId = _TestSites.First().Id;
            var homePageGuid = _TestPosts.First().PostGuid;
            var level1Guid = _TestPosts.Where(x => x.ParentGuid != null && x.ParentGuid.Value == homePageGuid).First().PostGuid;
            var level2Guid = _TestPosts.Where(x => x.ParentGuid != null && x.ParentGuid.Value == level1Guid).First().PostGuid;

            var level1Children = _TestPosts.Where(x => x.ParentGuid == level1Guid && x.PublishFrom == null).Count();
            Assert.AreEqual(2, level1Children);
            var level2Children = _TestPosts.Where(x => x.ParentGuid == level2Guid && x.PublishFrom == null).Count();
            Assert.AreEqual(1, level2Children);

            var level1ParentPath = _TestPosts.Where(x => x.PostGuid == level1Guid).First().PostPositions.Select(x => string.Concat(x.ParentPath, x.Post.Name, "/")).First();
            Assert.AreEqual("~/Child_1/", level1ParentPath);
            var level2ParentPath = _TestPosts.Where(x => x.PostGuid == level2Guid).First().PostPositions.Select(x => string.Concat(x.ParentPath, x.Post.Name, "/")).First(); ;

            Assert.AreEqual("~/Child_1/Child_1_1/", level2ParentPath);

            var tmp = Acms.Bll.Post.GetByPostGuid(_TestSites.First().Id, level1Guid, null);

            Assert.IsNotNull(tmp); 
            Assert.IsNotNull(tmp.ParentGuid);
            Assert.AreEqual(level1Children, Acms.Bll.Post.GetAllBySiteIdAndParentPath(siteId, level1ParentPath, null).Count);
            Assert.AreEqual(level2Children, Acms.Bll.Post.GetAllBySiteIdAndParentPath(siteId, level2ParentPath, null).Count);

            tmp.Name = "NewName";

            tmp.Update();

            Assert.AreEqual(level1Children, Acms.Bll.Post.GetAllBySiteIdAndParentPath(_TestSites.First().Id, "~/NewName", null).Count);

            Assert.AreEqual(level2Children, Acms.Bll.Post.GetAllBySiteIdAndParentPath(_TestSites.First().Id, "~/NewName/Child_1_1", null).Count);

        }

        [TestMethod]
        public void ChildPostsParentPaths_UpdateCorrectly_WhenChangingParentGuid() 
        {
            var originalParent = _TestPosts[5];
            var newParent = _TestPosts[7];
            var tmp = Post.GetAllByParentGuid(_TestSites.First().Id, originalParent.PostGuid, null);
            string expectedParentPath = string.Concat(_TestPosts[7].PostPositions[0].ParentPath, _TestPosts[7].Name, "/");
            
            Assert.AreEqual(2, tmp.Count);
            var postToChange = tmp.First();

            postToChange.ParentGuid = newParent.PostGuid;
            postToChange.Update();

            Assert.AreEqual(newParent.PostGuid, postToChange.ParentGuid);
            Assert.AreEqual(newParent.PostGuid, postToChange.Parent.PostGuid);
            Assert.AreEqual(expectedParentPath, postToChange.ParentPath);

            tmp = Post.GetAllByParentGuid(_TestSites.First().Id, originalParent.PostGuid, null);
            Assert.AreEqual(1, tmp.Count);

            tmp = Post.GetAllByParentGuid(_TestSites.First().Id, newParent.PostGuid, null);
            Assert.AreEqual(1, tmp.Count);

            Assert.AreEqual(expectedParentPath, _FreshContext.PostPositions.Where(x => x.PostId == postToChange.Id).Single().ParentPath);
        }

        [TestMethod]
        public void SettingPublishTo_StopsReturningPost()
        {
            // using post index 6 - Child 2 Published
            var tmp = Post.GetById(_TestSites.First().Id, _TestPosts[6].Id, DateTime.Now);
            Assert.IsNotNull(tmp, string.Format("Failed to load post with id {0} and version {1:yyyy/MM/dd HH:mm}", _TestPosts[6].Id, DateTime.Now));
            Assert.IsNull(tmp.PublishTo);
            tmp.PublishTo = DateTime.Now;
            tmp.Update();
            Assert.IsNotNull(tmp.PublishTo);
            Assert.IsNull(Post.GetById(_TestSites.First().Id, _TestPosts[6].Id, DateTime.Now));
        }

        [TestMethod]
        public void Retire_StopsReturningPost()
        {
            // using post index 6 - Child 2 Published
            var tmp = Post.GetById(_TestSites.First().Id, _TestPosts[6].Id, DateTime.Now);
            Assert.IsNotNull(tmp, string.Format("Failed to load post with id {0} and version {1:yyyy/MM/dd HH:mm}", _TestPosts[6].Id, DateTime.Now));
            Assert.IsNull(tmp.PublishTo);
            tmp.Retire();
            Assert.IsNotNull(tmp.PublishTo);
            Assert.IsNull(Post.GetById(_TestSites.First().Id, _TestPosts[6].Id, DateTime.Now));
        }

        [TestMethod]
        public void Retire_CreatesPostPostionRecord()
        {
            // using post index 6 - Child 2 Published
            var tmp = Post.GetById(_TestSites.First().Id, _TestPosts[6].Id, DateTime.Now);
            Assert.IsNotNull(tmp, string.Format("Failed to load post with id {0} and version {1:yyyy/MM/dd HH:mm}", _TestPosts[6].Id, DateTime.Now));
            Assert.IsNull(tmp.PublishTo);
            tmp.Retire();
            Assert.IsNotNull(tmp.PublishTo);
            //check there is at least some records in the postpostion a publish
            var tmpPostPositions = _FreshContext.PostPositions.Where(x => x.PublishDate == tmp.PublishTo.ToUniversalTime());
            var tmpPostIds = tmpPostPositions.Select(x => x.PostId);
            Assert.AreEqual(2, tmpPostPositions.Count());
            Assert.IsTrue(tmpPostIds.Contains(_TestPosts[1].Id));
            Assert.IsTrue(tmpPostIds.Contains(_TestPosts[4].Id));
            Assert.IsFalse(tmpPostIds.Contains(_TestPosts[6].Id));

            //check there is a new position record for each post
            foreach (var post in _FreshContext.Posts.Where(x => x.PublishFrom.HasValue && x.PublishFrom.Value <= tmp.PublishTo.Value.ToUniversalTime() && (x.PublishTo ?? DateTime.MaxValue) > tmp.PublishTo.ToUniversalTime()))
            {
                //date time hassels some milisecond discrapancy so complicated test for less than a second
                var pps = post.PostPositions.Where(x => x.PublishDate.HasValue && (x.PublishDate.Value - tmp.PublishTo.Value.ToUniversalTime()).Seconds > -1 && (x.PublishDate.Value - tmp.PublishTo.Value.ToUniversalTime()).Seconds < 1).Count();
                Assert.AreEqual(1, pps);
            }
        }

        [TestMethod]
        public void GetCurrentVersionsByPostId()
        {
            var tmp = Post.GetCurrentVersionsByPostId(_TestSites[0].Id, _TestPosts[0].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(3, tmp.Count());
            ValidateProperties(tmp[0], _TestPosts[1]);
            ValidateProperties(tmp[1], _TestPosts[2]);
            ValidateProperties(tmp[2], _TestPosts[3]);
        }

        [TestMethod]
        public void GetCurrentVersions()
        {
            var tmp = Post.GetCurrentVersions(_TestSites[0].Id, _TestPosts[0].PostGuid);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(3, tmp.Count());
            ValidateProperties(tmp[0], _TestPosts[1]);
            ValidateProperties(tmp[1], _TestPosts[2]);
            ValidateProperties(tmp[2], _TestPosts[3]);
        }

        private void ValidateProperties(Post post, TestData.Post data)
        {
            Assert.IsNotNull(post);
            Assert.IsNotNull(data);
            Assert.AreEqual(post.Id, data.Id);
            AssertHelper.AreEqual((byte[])post.ConcurencyId, data.VersionId);
            Assert.AreEqual(post.CreatedDateTime, data.CreatedDateTime.ToLocalTime());
            Assert.AreEqual(post.DeveloperLocked, data.DeveloperLocked);
            Assert.AreEqual(post.DisplayName, data.DisplayName);
            Assert.AreEqual(post.Name, data.Name);
            Assert.AreEqual(post.NodeType, (Template.NodeTypes)data.Template.NodeType);
            Assert.AreEqual(post.Notes, data.Notes);
            Assert.AreEqual(post.ParentGuid, data.ParentGuid);
            Assert.AreEqual(post.ParentPath, data.PostPositions.Where(x => x.PublishDate.ToLocalTime() == post.PublishFrom).First().ParentPath);
            Assert.AreEqual(post.PostGuid, data.PostGuid);
            Assert.AreEqual(post.PublishFrom, data.PublishFrom.ToLocalTime());
            Assert.AreEqual(post.PublishTo, data.PublishTo.ToLocalTime());
            Assert.AreEqual(post.ReadyToPublish, data.ReadyToPublish);
            Assert.AreEqual(post.RequiresPublishing, data.RequiresPublishing);
            Assert.AreEqual(post.Sequence, data.Sequence);
            Assert.AreEqual(post.SiteId, data.SiteId);
            Assert.AreEqual(post.Summary, data.Summary);
            Assert.AreEqual(post.TemplateId, data.TemplateId);
            Assert.AreEqual(post.ThumbnailId, data.ThumbnailId);
        }
    }
}
